#include "gateway_framework.hh"
#include "../../protocol_files/common/generated_proto_header.hh"
#include "../../protocol_files/dispatcher/msg_dispatcher.hh"
#include "../../corelib/util/os_util.hh"
#include "client.hh"

GatewayFramework::GatewayFramework()
    : maxBufferredMsgCount_(DEFAULT_MAX_BUFFERRED_MSG_COUNT){
}

GatewayFramework::~GatewayFramework() {
}

bool GatewayFramework::onStart(kconfig::Config * config) {
    verblog << "Module gateway started" << endlog;
    if (config->has("engine.gateway.maxBufferredMsgCount")) {
        try {
            maxBufferredMsgCount_ = config->getUint32("engine.gateway.maxBufferredMsgCount");
        } catch (std::exception& e) {
            errorlog << "Invalid parameter: engine.gateway.maxBufferredMsgCount, exception reason:" << e.what() << endlog;
            return false;
        }
        if (!maxBufferredMsgCount_) {
            maxBufferredMsgCount_ = UINT_MAX;
        }
    }
    std::string configPath;
    configPath = kratos::corelib::OS::completePath(getRootPath(), "msg_dispatcher.cfg");
    if (!MsgDispatcherRef.start(configPath)) {
        errorlog << "Message dispatcher not found or meet some error:" << configPath << endlog;
        return false;
    }
    return true;
}

bool GatewayFramework::onStop() {
    verblog << "Module gateway stopped" << endlog;
    return true;
}

void GatewayFramework::onTick(std::time_t millionseconds) {
    static std::time_t tick = 0;
    if (!tick) {
        tick = millionseconds;
    }
    if (millionseconds - tick > 5000) {
        verblog << "client size:" << pathSessionMap_.size() << endlog;
        tick = millionseconds;
    }
}

void GatewayFramework::onPathJoin(PathID pathID, SiteType siteType, UserData userData) {
    auto sessionID = static_cast<SessionID>(userData);
    auto client = ClientManagerRef.get(sessionID);
    if (client) {
        client->newPath(pathID, siteType);
        pathSessionMap_[pathID] = sessionID;
    } else {
        FrameworkRef.closePath(pathID);
    }
}

void GatewayFramework::onPathDisjoin(PathID pathID, SiteType siteType) {
    auto it = pathSessionMap_.find(pathID);
    if (it == pathSessionMap_.end()) {
        return;
    }
    auto client = ClientManagerRef.get(it->second);
    if (client) {
        client->removePath(pathID, siteType);
    }
    pathSessionMap_.erase(it);
}

void GatewayFramework::onPathData(PathID pathID, SiteType siteType,
    std::uint32_t msgID, const char * data, std::size_t size) {
    auto it = pathSessionMap_.find(pathID);
    if (it == pathSessionMap_.end()) {
        return;
    }
    //verblog << "To client, size:" << size << ",MSGID:" << msgID << endlog;
    auto client = ClientManagerRef.get(it->second);
    if (client) {
        client->toClient(data, size);
    }
}

void GatewayFramework::onSessionJoin(SessionID sessionID) {
    ClientManagerRef.add(sessionID);
}

void GatewayFramework::onSessionDisjoin(SessionID sessionID) {
    ClientManagerRef.remove(sessionID);
}

void GatewayFramework::onSessionData(SessionID sessionID, std::uint32_t msgID,
    const char * data, std::size_t size) {
    //verblog << "Receive, size:" << size << ", MSGID:" << msgID << endlog;
    auto client = ClientManagerRef.get(sessionID);
    if (client) {
        client->fromClient(msgID, data, size);
    }
}

std::uint32_t GatewayFramework::getMaxBufferredMsgCount() const {
    return maxBufferredMsgCount_;
}
